﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Data.OleDb; 
using System.Data.Common;
using System.Data;
using System.Data.SqlClient;
using NpgsqlTypes;
using System.Xml;
using System.Reflection;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Globalization;

namespace TestDataDriver
{
    interface IDbDriver
    {
        DbConnection CreateConnection();
         
        DbCommand CreateCommand();
         
        int GetDataReaderSpecificFieldType(DbDataReader dataReader, int columnIndex);
    }

    class SqlServerDriver : IDbDriver 
    {

        //DONE: test done
        /*
         CREATE TABLE [dbo].[T1](
	[F_Int] [int] NULL,
	[F_char] [char](10) COLLATE Chinese_PRC_CI_AS NULL,
	[F_Varchar] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
	[F_bit] [bit] NULL,
	[F_nvarchar] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,
	[F_nchar] [nchar](10) COLLATE Chinese_PRC_CI_AS NULL,
	[F_Datetime] [datetime] NULL,
	[F_double] [real] NULL
) ON [PRIMARY]

GO
         
         */
        public DbConnection CreateConnection()
        {
            return new SqlConnection();
        }

        public DbCommand CreateCommand()
        {
            return new SqlCommand();
        }

        public int GetDataReaderSpecificFieldType(DbDataReader dataReader, int columnIndex)
        {
            //class: System.Data.SqlClient.SqlDataReader
            //method: public override string GetDataTypeName(int i)

            //var method = dataReader.GetType().GetMethod("GetDataTypeName");
            //var parameters = new object[] { columnIndex };
            //var typeName = (string)method.Invoke(dataReader, parameters);
            //return (int)Enum.Parse(typeof(SqlDbType), typeName, true);

            var reader = (System.Data.SqlClient.SqlDataReader)dataReader;
            var typeName = reader.GetDataTypeName(columnIndex);
            return (int)Enum.Parse(typeof(SqlDbType), typeName, true);
        }
    }

    class PostgresDriver : IDbDriver
    {
        //DONE: test done

        /*
         CREATE TABLE t1
(
  f_int integer,
  f_char "char",
  f_varchar character varying(10),
  "f_timestampTZ" timestamp with time zone[],
  f_number numeric(10,1),
  "f_Interval" interval,
  f_money money,
  "f_Time" time with time zone
)
WITH (OIDS=FALSE);
         
         */

        public int GetDataReaderSpecificFieldType(DbDataReader dataReader, int columnIndex)
        {
            //class: Npgsql.NpgsqlDataReader
            //method: public NpgsqlDbType GetFieldNpgsqlDbType(int Index)


            //var method = dataReader.GetType().GetMethod("GetFieldNpgsqlDbType");
            //var parameters = new object[] { columnIndex };
            //return (int)method.Invoke(dataReader, parameters);

            var reader = (Npgsql.NpgsqlDataReader)dataReader;
            return (int)reader.GetFieldNpgsqlDbType(columnIndex);
        }

        public DbConnection CreateConnection()
        {
            return new Npgsql.NpgsqlConnection();
        }

        public DbCommand CreateCommand()
        {
            return new Npgsql.NpgsqlCommand();
        }

       
    }


    class OracleDriver : IDbDriver
    {
        //DONE: test done


                /*
         -- Create table
create table t1
(
  f_interval_ts  interval day to second,
  f_interval_ym  interval year to month,
  f_timestamp    timestamp,
  f_timestamp_tz timestamp with time zone,
  f_varchar2     varchar2(10),
  f_date         date,
  f_char         char(1),
  f_number       number,
  f_interger     number(18,0)
)
;
*/


        public int GetDataReaderSpecificFieldType(DbDataReader dataReader, int columnIndex)
        {
            //class: System.Data.OracleClient.OracleDataReader
            //method: public override string GetDataTypeName(int i)

            //var method = dataReader.GetType().GetMethod("GetDataTypeName");
            //var parameters = new object[] { columnIndex };
            //var typeName = (string)method.Invoke(dataReader, parameters);

            var reader = (System.Data.OracleClient.OracleDataReader)dataReader;
            var typeName = reader.GetDataTypeName(columnIndex);

            //The following constant values is taken in class of System.Data.OracleClient.MetaType
            const string N_BFILE = "BFILE";
            const string N_BLOB = "BLOB";
            const string N_CHAR = "CHAR";
            const string N_CLOB = "CLOB";
            const string N_DATE = "DATE";
            const string N_FLOAT = "FLOAT";
            const string N_INTEGER = "INTEGER";
            const string N_INTERVALDS = "INTERVAL DAY TO SECOND";
            const string N_INTERVALYM = "INTERVAL YEAR TO MONTH";
            const string N_LONG = "LONG";
            const string N_LONGRAW = "LONG RAW";
            const string N_NCHAR = "NCHAR";
            const string N_NCLOB = "NCLOB";
            const string N_NUMBER = "NUMBER";
            const string N_NVARCHAR2 = "NVARCHAR2";
            const string N_RAW = "RAW";
            const string N_REFCURSOR = "REF CURSOR";
            const string N_ROWID = "ROWID";
            const string N_TIMESTAMP = "TIMESTAMP";
            const string N_TIMESTAMPLTZ = "TIMESTAMP WITH LOCAL TIME ZONE";
            const string N_TIMESTAMPTZ = "TIMESTAMP WITH TIME ZONE";
            const string N_UNSIGNEDINT = "UNSIGNED INTEGER";
            const string N_VARCHAR2 = "VARCHAR2";

            var metaTypeMapping = new Dictionary<string, System.Data.OracleClient.OracleType>();
            metaTypeMapping.Add(N_BFILE, System.Data.OracleClient.OracleType.BFile);
            metaTypeMapping.Add(N_BLOB, System.Data.OracleClient.OracleType.Blob);

            metaTypeMapping.Add(N_CHAR, System.Data.OracleClient.OracleType.Char);
            metaTypeMapping.Add(N_CLOB, System.Data.OracleClient.OracleType.Clob);
            metaTypeMapping.Add(N_DATE, System.Data.OracleClient.OracleType.DateTime);
            metaTypeMapping.Add(N_FLOAT, System.Data.OracleClient.OracleType.Float);
            metaTypeMapping.Add(N_INTEGER, System.Data.OracleClient.OracleType.Int32);

            metaTypeMapping.Add(N_INTERVALDS, System.Data.OracleClient.OracleType.IntervalDayToSecond);
            metaTypeMapping.Add(N_INTERVALYM, System.Data.OracleClient.OracleType.IntervalYearToMonth);
            metaTypeMapping.Add(N_LONG, System.Data.OracleClient.OracleType.LongVarChar);
            metaTypeMapping.Add(N_LONGRAW, System.Data.OracleClient.OracleType.LongRaw);
            metaTypeMapping.Add(N_NCHAR, System.Data.OracleClient.OracleType.NChar);
            metaTypeMapping.Add(N_NCLOB, System.Data.OracleClient.OracleType.NClob);
            metaTypeMapping.Add(N_NUMBER, System.Data.OracleClient.OracleType.Number);
            metaTypeMapping.Add(N_NVARCHAR2, System.Data.OracleClient.OracleType.NVarChar);
            metaTypeMapping.Add(N_RAW, System.Data.OracleClient.OracleType.Raw);
            metaTypeMapping.Add(N_REFCURSOR, System.Data.OracleClient.OracleType.Cursor);

            metaTypeMapping.Add(N_ROWID, System.Data.OracleClient.OracleType.RowId);
            metaTypeMapping.Add(N_TIMESTAMP, System.Data.OracleClient.OracleType.Timestamp);
            metaTypeMapping.Add(N_TIMESTAMPLTZ, System.Data.OracleClient.OracleType.TimestampLocal);
            metaTypeMapping.Add(N_TIMESTAMPTZ, System.Data.OracleClient.OracleType.TimestampWithTZ);
            metaTypeMapping.Add(N_UNSIGNEDINT, System.Data.OracleClient.OracleType.UInt32);
            metaTypeMapping.Add(N_VARCHAR2, System.Data.OracleClient.OracleType.VarChar);

            System.Data.OracleClient.OracleType result;
            var found = metaTypeMapping.TryGetValue(typeName, out result);
            if (found)
                return (int)result;
            else
                return -1;

        }

  

        public DbConnection CreateConnection()
        {
            return new  System.Data.OracleClient.OracleConnection ();
        }

        public DbCommand CreateCommand()
        {
            return new System.Data.OracleClient.OracleCommand();
        }

       
    }


    class OracleDriver2 : IDbDriver
    {
        //Done: need to test 

        /*
         -- Create table
create table t1
(
  f_interval_ts  interval day to second,
  f_interval_ym  interval year to month,
  f_timestamp    timestamp,
  f_timestamp_tz timestamp with time zone,
  f_varchar2     varchar2(10),
  f_date         date,
  f_char         char(1),
  f_number       number,
  f_interger     number(18,0)
)
;

         */
        public int GetDataReaderSpecificFieldType(DbDataReader dataReader, int columnIndex)
        {
            //class: Devart.Data.Oracle.OracleDataReader
            //method: public OracleType GetObjectType(int i)

            //  //******GetObjectType method does not work in current devart ado.net, at least 5.70.170.0 and below
            //var method = dataReader.GetType().GetMethod("GetObjectType");
            //var parameters = new object[] { columnIndex };
            //var type= (Devart.Data.Oracle.OracleType)method.Invoke(dataReader, parameters);
            //return (int)type.DbType;

            int providerDbType = -1;

            var reader = (Devart.Data.Oracle.OracleDataReader)dataReader;
            var typeName = reader.GetDataTypeName(columnIndex);

            //Devart.Data.Oracle.OracleDataTypes.xml contains name and enum index pair of OracleDbType
            var stream = Assembly.GetAssembly(dataReader.GetType()).GetManifestResourceStream("Devart.Data.Oracle.OracleDataTypes.xml");
            var xmlReader = new XmlTextReader(stream);
            var xmlDocument = XDocument.Load(xmlReader);
            string xPath = "/NewDataSet/DataTypes/TypeName";
            var typeNameElements = xmlDocument.XPathSelectElements(xPath);
            XElement typeNameElement = null;
            foreach (var item in typeNameElements)
            {
                string name2 = item.Value.Trim();
                if (string.Equals(typeName, name2, StringComparison.Ordinal))
                {
                    typeNameElement = item;
                    break;
                }
            }
            if (typeNameElement != null)
            {
                XElement providerDbTypeElement = typeNameElement.Parent.Element("ProviderDbType");
                providerDbType = int.Parse(providerDbTypeElement.Value.Trim());
            }
            return providerDbType;
        }



        public DbConnection CreateConnection()
        {
            return new Devart.Data.Oracle.OracleConnection();
        }

        public DbCommand CreateCommand()
        {
            return new Devart.Data.Oracle.OracleCommand();
        }


    }


    class MySqlDriver : IDbDriver
    {
        //Done: need to test 

        private bool IsAtLeast(string serverVersion, int majorNum, int minorNum, int buildNum)
        {
            var versionParts = serverVersion.Split(new char[] { '.' });
            var thisMajor = int.Parse(versionParts[0]);
            var thisMinor = int.Parse(versionParts[1]);
            var thisBuild = int.Parse(versionParts[2]);
            return ((thisMajor > majorNum) || (((thisMajor == majorNum) && (thisMinor > minorNum)) || (((thisMajor == majorNum) && (thisMinor == minorNum)) && (thisBuild >= buildNum))));
        }

        //private MySqlDbType NameToType(string typeName, bool unsigned, bool realAsFloat, MySqlConnection connection)
        private MySqlDbType NameToType(string typeName, bool unsigned, bool realAsFloat)
        {
            switch (typeName.ToLower(CultureInfo.InvariantCulture))
            {
                case "char":
                    return MySqlDbType.String;

                case "varchar":
                    return MySqlDbType.VarChar;

                case "date":
                    return MySqlDbType.Date;

                case "datetime":
                    return MySqlDbType.DateTime;

                case "numeric":
                case "decimal":
                case "dec":
                case "fixed":

                    //if (!IsAtLeast(connection.ServerVersion, 5, 0, 3))
                    //{
                    //    return MySqlDbType.Decimal;
                    //}
                    return MySqlDbType.NewDecimal;

                case "year":
                    return MySqlDbType.Year;

                case "time":
                    return MySqlDbType.Time;

                case "timestamp":
                    return MySqlDbType.Timestamp;

                case "set":
                    return MySqlDbType.Set;

                case "enum":
                    return MySqlDbType.Enum;

                case "bit":
                    return MySqlDbType.Bit;

                case "tinyint":
                    if (unsigned)
                    {
                        return MySqlDbType.UByte;
                    }
                    return MySqlDbType.Byte;

                case "bool":
                case "boolean":
                    return MySqlDbType.Byte;

                case "smallint":
                    if (unsigned)
                    {
                        return MySqlDbType.UInt16;
                    }
                    return MySqlDbType.Int16;

                case "mediumint":
                    if (unsigned)
                    {
                        return MySqlDbType.UInt24;
                    }
                    return MySqlDbType.Int24;

                case "int":
                case "integer":
                    if (unsigned)
                    {
                        return MySqlDbType.UInt32;
                    }
                    return MySqlDbType.Int32;

                case "serial":
                    return MySqlDbType.UInt64;

                case "bigint":
                    if (unsigned)
                    {
                        return MySqlDbType.UInt64;
                    }
                    return MySqlDbType.Int64;

                case "float":
                    return MySqlDbType.Float;

                case "double":
                    return MySqlDbType.Double;

                case "real":
                    if (realAsFloat)
                    {
                        return MySqlDbType.Float;
                    }
                    return MySqlDbType.Double;

                case "text":
                    return MySqlDbType.Text;

                case "blob":
                    return MySqlDbType.Blob;

                case "longblob":
                    return MySqlDbType.LongBlob;

                case "longtext":
                    return MySqlDbType.LongText;

                case "mediumblob":
                    return MySqlDbType.MediumBlob;

                case "mediumtext":
                    return MySqlDbType.MediumText;

                case "tinyblob":
                    return MySqlDbType.TinyBlob;

                case "tinytext":
                    return MySqlDbType.TinyText;

                case "binary":
                    return MySqlDbType.Binary;

                case "varbinary":
                    return MySqlDbType.VarBinary;
            }
            throw new NotSupportedException("Unhandled type encountered");
        }


        public int GetDataReaderSpecificFieldType(DbDataReader dataReader, int columnIndex)
        {
            //class: MySql.Data.MySqlClient.MySqlDataReader
            //method: public override string GetDataTypeName(int i)
 
            var reader = (MySql.Data.MySqlClient.MySqlDataReader)dataReader;
            var typeName = reader.GetDataTypeName(columnIndex);
            var mySqlDbType = NameToType(typeName, false, false);
            return (int)mySqlDbType;
        }
    

        public DbConnection CreateConnection()
        {
            return new MySqlConnection();
        }
 
        public DbCommand CreateCommand()
        {
            return new MySqlCommand ();
        }
 
    }

    class OleDbDriver : IDbDriver
    { 
  //DONE: test done on SQL SERVER
        /*
         CREATE TABLE [dbo].[T1](
	[F_Int] [int] NULL,
	[F_char] [char](10) COLLATE Chinese_PRC_CI_AS NULL,
	[F_Varchar] [varchar](50) COLLATE Chinese_PRC_CI_AS NULL,
	[F_bit] [bit] NULL,
	[F_nvarchar] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,
	[F_nchar] [nchar](10) COLLATE Chinese_PRC_CI_AS NULL,
	[F_Datetime] [datetime] NULL,
	[F_double] [real] NULL
) ON [PRIMARY]

GO
         * */

        public int GetDataReaderSpecificFieldType(DbDataReader dataReader, int columnIndex)
        {
            //class: System.Data.OleDb.OleDbDataReader
            //method: public override string GetDataTypeName(int index)

            //var method = dataReader.GetType().GetMethod("GetDataTypeName");
            //var parameters = new object[] { columnIndex };
            //var typeName = (string)method.Invoke(dataReader, parameters);

            var reader = (System.Data.OleDb.OleDbDataReader)dataReader;
            var typeName = reader.GetDataTypeName(columnIndex);


            //The following constant values is taken in class of System.Data.OleDb.NativeDBType
            /*
              private static readonly NativeDBType D_BigInt = new NativeDBType(0x13, 8, true, false, OleDbType.BigInt, 20, "DBTYPE_I8", typeof(long), 20, DbType.Int64);
              private static readonly NativeDBType D_Binary = new NativeDBType(0xff, -1, true, false, OleDbType.Binary, 0x80, "DBTYPE_BINARY", typeof(byte[]), 0x80, DbType.Binary);
              private static readonly NativeDBType D_Boolean = new NativeDBType(0xff, 2, true, false, OleDbType.Boolean, 11, "DBTYPE_BOOL", typeof(bool), 11, DbType.Boolean);
              private static readonly NativeDBType D_BSTR = new NativeDBType(0xff, ADP.PtrSize, false, false, OleDbType.BSTR, 8, "DBTYPE_BSTR", typeof(string), 8, DbType.String);
              private static readonly NativeDBType D_Chapter = new NativeDBType(0xff, ADP.PtrSize, false, false, OleDbType.Empty, 0x88, "DBTYPE_UDT", typeof(IDataReader), 0x88, DbType.Object);
              private static readonly NativeDBType D_Char = new NativeDBType(0xff, -1, true, false, OleDbType.Char, 0x81, "DBTYPE_CHAR", typeof(string), 130, DbType.AnsiStringFixedLength);
              private static readonly NativeDBType D_Currency = new NativeDBType(0x13, 8, true, false, OleDbType.Currency, 6, "DBTYPE_CY", typeof(decimal), 6, DbType.Currency);
              private static readonly NativeDBType D_Date = new NativeDBType(0xff, 8, true, false, OleDbType.Date, 7, "DBTYPE_DATE", typeof(DateTime), 7, DbType.DateTime);
              private static readonly NativeDBType D_DBDate = new NativeDBType(0xff, 6, true, false, OleDbType.DBDate, 0x85, "DBTYPE_DBDATE", typeof(DateTime), 0x85, DbType.Date);
              private static readonly NativeDBType D_DBTime = new NativeDBType(0xff, 6, true, false, OleDbType.DBTime, 0x86, "DBTYPE_DBTIME", typeof(TimeSpan), 0x86, DbType.Time);
              private static readonly NativeDBType D_DBTimeStamp = new NativeDBType(0xff, 0x10, true, false, OleDbType.DBTimeStamp, 0x87, "DBTYPE_DBTIMESTAMP", typeof(DateTime), 0x87, DbType.DateTime);
              private static readonly NativeDBType D_Decimal = new NativeDBType(0x1c, 0x10, true, false, OleDbType.Decimal, 14, "DBTYPE_DECIMAL", typeof(decimal), 14, DbType.Decimal);
              private static readonly NativeDBType D_Double = new NativeDBType(15, 8, true, false, OleDbType.Double, 5, "DBTYPE_R8", typeof(double), 5, DbType.Double);
              private static readonly NativeDBType D_Empty = new NativeDBType(0xff, 0, false, false, OleDbType.Empty, 0, "", null, 0, DbType.Object);
              private static readonly NativeDBType D_Error = new NativeDBType(0xff, 4, true, false, OleDbType.Error, 10, "DBTYPE_ERROR", typeof(int), 10, DbType.Int32);
              private static readonly NativeDBType D_Filetime = new NativeDBType(0xff, 8, true, false, OleDbType.Filetime, 0x40, "DBTYPE_FILETIME", typeof(DateTime), 0x40, DbType.DateTime);
              private static readonly NativeDBType D_Guid = new NativeDBType(0xff, 0x10, true, false, OleDbType.Guid, 0x48, "DBTYPE_GUID", typeof(Guid), 0x48, DbType.Guid);
              private static readonly NativeDBType D_IDispatch = new NativeDBType(0xff, ADP.PtrSize, true, false, OleDbType.IDispatch, 9, "DBTYPE_IDISPATCH", typeof(object), 9, DbType.Object);
              private static readonly NativeDBType D_Integer = new NativeDBType(10, 4, true, false, OleDbType.Integer, 3, "DBTYPE_I4", typeof(int), 3, DbType.Int32);
              private static readonly NativeDBType D_IUnknown = new NativeDBType(0xff, ADP.PtrSize, true, false, OleDbType.IUnknown, 13, "DBTYPE_IUNKNOWN", typeof(object), 13, DbType.Object);
              private static readonly NativeDBType D_LongVarBinary = new NativeDBType(0xff, -1, false, true, OleDbType.LongVarBinary, 0x80, "DBTYPE_LONGVARBINARY", typeof(byte[]), 0x80, DbType.Binary);
              private static readonly NativeDBType D_LongVarChar = new NativeDBType(0xff, -1, false, true, OleDbType.LongVarChar, 0x81, "DBTYPE_LONGVARCHAR", typeof(string), 130, DbType.AnsiString);
              private static readonly NativeDBType D_LongVarWChar = new NativeDBType(0xff, -1, false, true, OleDbType.LongVarWChar, 130, "DBTYPE_WLONGVARCHAR", typeof(string), 130, DbType.String);
              private static readonly NativeDBType D_Numeric = new NativeDBType(0x1c, 0x13, true, false, OleDbType.Numeric, 0x83, "DBTYPE_NUMERIC", typeof(decimal), 0x83, DbType.Decimal);
              private static readonly NativeDBType D_PropVariant = new NativeDBType(0xff, NativeOledbWrapper.SizeOfPROPVARIANT, true, false, OleDbType.PropVariant, 0x8a, "DBTYPE_PROPVARIANT", typeof(object), 12, DbType.Object);
              private static readonly NativeDBType D_Single = new NativeDBType(7, 4, true, false, OleDbType.Single, 4, "DBTYPE_R4", typeof(float), 4, DbType.Single);
              private static readonly NativeDBType D_SmallInt = new NativeDBType(5, 2, true, false, OleDbType.SmallInt, 2, "DBTYPE_I2", typeof(short), 2, DbType.Int16);
              private static readonly NativeDBType D_TinyInt = new NativeDBType(3, 1, true, false, OleDbType.TinyInt, 0x10, "DBTYPE_I1", typeof(short), 0x10, DbType.SByte);
              private static readonly NativeDBType D_Udt = new NativeDBType(0xff, -1, false, false, OleDbType.VarBinary, 0x84, "DBTYPE_BINARY", typeof(byte[]), 0x80, DbType.Binary);
              private static readonly NativeDBType D_UnsignedBigInt = new NativeDBType(20, 8, true, false, OleDbType.UnsignedBigInt, 0x15, "DBTYPE_UI8", typeof(decimal), 0x15, DbType.UInt64);
              private static readonly NativeDBType D_UnsignedInt = new NativeDBType(10, 4, true, false, OleDbType.UnsignedInt, 0x13, "DBTYPE_UI4", typeof(long), 0x13, DbType.UInt32);
              private static readonly NativeDBType D_UnsignedSmallInt = new NativeDBType(5, 2, true, false, OleDbType.UnsignedSmallInt, 0x12, "DBTYPE_UI2", typeof(int), 0x12, DbType.UInt16);
              private static readonly NativeDBType D_UnsignedTinyInt = new NativeDBType(3, 1, true, false, OleDbType.UnsignedTinyInt, 0x11, "DBTYPE_UI1", typeof(byte), 0x11, DbType.Byte);
              private static readonly NativeDBType D_VarBinary = new NativeDBType(0xff, -1, false, false, OleDbType.VarBinary, 0x80, "DBTYPE_VARBINARY", typeof(byte[]), 0x80, DbType.Binary);
              private static readonly NativeDBType D_VarChar = new NativeDBType(0xff, -1, false, false, OleDbType.VarChar, 0x81, "DBTYPE_VARCHAR", typeof(string), 130, DbType.AnsiString);
              private static readonly NativeDBType D_Variant = new NativeDBType(0xff, ODB.SizeOf_Variant, true, false, OleDbType.Variant, 12, "DBTYPE_VARIANT", typeof(object), 12, DbType.Object);
              private static readonly NativeDBType D_VarNumeric = new NativeDBType(0xff, 0x10, true, false, OleDbType.VarNumeric, 0x8b, "DBTYPE_VARNUMERIC", typeof(decimal), 14, DbType.VarNumeric);
              private static readonly NativeDBType D_VarWChar = new NativeDBType(0xff, -1, false, false, OleDbType.VarWChar, 130, "DBTYPE_WVARCHAR", typeof(string), 130, DbType.String);
              private static readonly NativeDBType D_WChar = new NativeDBType(0xff, -1, true, false, OleDbType.WChar, 130, "DBTYPE_WCHAR", typeof(string), 130, DbType.StringFixedLength);
              private static readonly NativeDBType D_Xml = new NativeDBType(0xff, -1, false, false, OleDbType.VarWChar, 0x8d, "DBTYPE_XML", typeof(string), 130, DbType.String);
           */

            var metaTypeMapping = new Dictionary<string, OleDbType>();
            metaTypeMapping.Add("DBTYPE_I8", OleDbType.BigInt);
            metaTypeMapping.Add("DBTYPE_BINARY", OleDbType.Binary);
            metaTypeMapping.Add("DBTYPE_BOOL", OleDbType.Boolean);
            metaTypeMapping.Add("DBTYPE_BSTR", OleDbType.BSTR);
            metaTypeMapping.Add("DBTYPE_UDT", OleDbType.Empty);
            metaTypeMapping.Add("DBTYPE_CHAR", OleDbType.Char);
            metaTypeMapping.Add("DBTYPE_CY", OleDbType.Currency);
            metaTypeMapping.Add("DBTYPE_DATE", OleDbType.Date);
            metaTypeMapping.Add("DBTYPE_DBDATE", OleDbType.DBDate);
            metaTypeMapping.Add("DBTYPE_DBTIME", OleDbType.DBTime);
            metaTypeMapping.Add("DBTYPE_DBTIMESTAMP", OleDbType.DBTimeStamp);
            metaTypeMapping.Add("DBTYPE_DECIMAL", OleDbType.Decimal);
            metaTypeMapping.Add("DBTYPE_R8", OleDbType.Double);
            metaTypeMapping.Add("", OleDbType.Empty);
            metaTypeMapping.Add("DBTYPE_ERROR", OleDbType.Error);
            metaTypeMapping.Add("DBTYPE_FILETIME", OleDbType.Filetime);
            metaTypeMapping.Add("DBTYPE_GUID", OleDbType.Guid);
            metaTypeMapping.Add("DBTYPE_IDISPATCH", OleDbType.IDispatch);
            metaTypeMapping.Add("DBTYPE_I4", OleDbType.Integer);
            metaTypeMapping.Add("DBTYPE_IUNKNOWN", OleDbType.IUnknown);
            metaTypeMapping.Add("DBTYPE_LONGVARBINARY", OleDbType.LongVarBinary);
            metaTypeMapping.Add("DBTYPE_LONGVARCHAR", OleDbType.LongVarChar);
            metaTypeMapping.Add("DBTYPE_WLONGVARCHAR", OleDbType.LongVarWChar);
            metaTypeMapping.Add("DBTYPE_NUMERIC", OleDbType.Numeric);
            metaTypeMapping.Add("DBTYPE_PROPVARIANT", OleDbType.PropVariant);
            metaTypeMapping.Add("DBTYPE_R4", OleDbType.Single);
            metaTypeMapping.Add("DBTYPE_I2", OleDbType.SmallInt);
            metaTypeMapping.Add("DBTYPE_I1", OleDbType.TinyInt);
            //metaTypeMapping.Add("DBTYPE_BINARY", OleDbType.VarBinary);
            metaTypeMapping.Add("DBTYPE_UI8", OleDbType.UnsignedBigInt);
            metaTypeMapping.Add("DBTYPE_UI4", OleDbType.UnsignedInt);
            metaTypeMapping.Add("DBTYPE_UI2", OleDbType.UnsignedSmallInt);
            metaTypeMapping.Add("DBTYPE_UI1", OleDbType.UnsignedTinyInt);
            metaTypeMapping.Add("DBTYPE_VARBINARY", OleDbType.VarBinary);
            metaTypeMapping.Add("DBTYPE_VARCHAR", OleDbType.VarChar);
            metaTypeMapping.Add("DBTYPE_VARIANT", OleDbType.Variant);
            metaTypeMapping.Add("DBTYPE_VARNUMERIC", OleDbType.VarNumeric);
            metaTypeMapping.Add("DBTYPE_WVARCHAR", OleDbType.VarWChar);
            metaTypeMapping.Add("DBTYPE_WCHAR", OleDbType.WChar);
            metaTypeMapping.Add("DBTYPE_XML", OleDbType.VarWChar);


            OleDbType result;
            var found = metaTypeMapping.TryGetValue(typeName, out result);
            if (found)
                return (int)result;
            else
                return -1;
        }


        

        public DbConnection CreateConnection()
        {
            return new OleDbConnection();
        }

        public DbCommand CreateCommand()
        {
            return new OleDbCommand();
        }

        
    }

}
